#packagejson转为js#
import json
import os
import argparse
import shlex
import sys
from pathlib import Path

def find_package_json(package_dir):
    """
    查找package.json文件，可能在根目录或package子目录
    """
    package_path = Path(package_dir)
    
    # 首先在根目录查找
    root_package_json = package_path / "package.json"
    if root_package_json.exists():
        return root_package_json
    
    # 然后在package子目录查找
    package_subdir_json = package_path / "package" / "package.json"
    if package_subdir_json.exists():
        return package_subdir_json
    
    # 递归查找第一个package.json
    for package_json in package_path.rglob("package.json"):
        if "node_modules" not in package_json.parts:
            return package_json
    
    return None

def process_package(package_dir):
    """
    处理npm包，提取package.json中的脚本并转换为虚拟JS文件
    """
    package_path = Path(package_dir)
    
    js_files = []
    
    # 收集所有现有的.js文件
    for js_file in package_path.rglob("*.js"):
        if "node_modules" not in js_file.parts:
            js_files.append(str(js_file.absolute()))
    
    # 查找package.json
    package_json_path = find_package_json(package_dir)
    
    if package_json_path:
        print(f"DEBUG: Found package.json at: {package_json_path}", file=sys.stderr)
        
        try:
            with open(package_json_path, 'r', encoding='utf-8') as f:
                content = f.read()
                print(f"DEBUG: package.json content length: {len(content)}", file=sys.stderr)
                
            # 重新读取并解析JSON
            with open(package_json_path, 'r', encoding='utf-8') as f:
                package_data = json.load(f)
            
            scripts = package_data.get('scripts', {})
            print(f"DEBUG: Found scripts: {scripts}", file=sys.stderr)
            
            target_hooks = ['preinstall', 'install', 'postinstall']
            spawn_calls = []
            
            for hook in target_hooks:
                if hook in scripts:
                    script_command = scripts[hook]
                    print(f"DEBUG: Processing {hook}: {script_command}", file=sys.stderr)
                    
                    if script_command and script_command.strip():
                        converted_calls = convert_script_to_spawn(script_command)
                        print(f"DEBUG: Converted to {len(converted_calls)} spawn calls", file=sys.stderr)
                        spawn_calls.extend(converted_calls)
            
            # 如果有spawn调用，创建虚拟JS文件
            if spawn_calls:
                print(f"DEBUG: Creating virtual file with {len(spawn_calls)} calls", file=sys.stderr)
                
                # 虚拟文件放在包的根目录
                virtual_file_path = package_path / "_virtual_package_script.js"
                
                with open(virtual_file_path, 'w', encoding='utf-8') as f:
                    f.write("// Virtual script file generated from package.json scripts\n")
                    f.write("const { spawn } = require('child_process');\n\n")
                    for i, call in enumerate(spawn_calls, 1):
                        f.write(f"// Command {i}\n")
                        f.write(call + "\n\n")
                
                js_files.append(str(virtual_file_path.absolute()))
                print(f"DEBUG: Virtual file created: {virtual_file_path}", file=sys.stderr)
            else:
                print("DEBUG: No spawn calls generated", file=sys.stderr)
        
        except json.JSONDecodeError as e:
            print(f"DEBUG: JSON decode error: {e}", file=sys.stderr)
        except Exception as e:
            print(f"DEBUG: Error processing package.json: {e}", file=sys.stderr)
            import traceback
            traceback.print_exc(file=sys.stderr)
    else:
        print("DEBUG: No package.json found", file=sys.stderr)
    
    return js_files

def convert_script_to_spawn(script_command):
    """
    将脚本命令转换为spawn调用
    """
    print(f"DEBUG: Converting script: {script_command}", file=sys.stderr)
    
    spawn_calls = []
    
    # 处理&&分隔的多个命令
    commands = script_command.split('&&')
    
    for command in commands:
        command = command.strip()
        if not command:
            continue
        
        print(f"DEBUG: Processing command: {command}", file=sys.stderr)
        
        try:
            # 使用shlex分割命令和参数
            parts = shlex.split(command)
            if parts:
                cmd = parts[0]
                args = parts[1:] if len(parts) > 1 else []
                
                print(f"DEBUG: Command: {cmd}, Args: {args}", file=sys.stderr)
                
                # 构造spawn调用字符串
                if args:
                    # 正确处理参数中的特殊字符
                    args_str = ', '.join([repr(arg) for arg in args])
                    spawn_call = f"spawn({repr(cmd)}, [{args_str}]);"
                else:
                    spawn_call = f"spawn({repr(cmd)}, []);"
                
                spawn_calls.append(spawn_call)
                print(f"DEBUG: Generated spawn call: {spawn_call}", file=sys.stderr)
        
        except ValueError as e:
            print(f"DEBUG: Shlex error: {e}, using simple split", file=sys.stderr)
            # 如果shlex无法解析，使用简单的空格分割
            parts = command.split()
            if parts:
                cmd = parts[0]
                args = parts[1:] if len(parts) > 1 else []
                
                if args:
                    args_str = ', '.join([repr(arg) for arg in args])
                    spawn_call = f"spawn({repr(cmd)}, [{args_str}]);"
                else:
                    spawn_call = f"spawn({repr(cmd)}, []);"
                
                spawn_calls.append(spawn_call)
    
    return spawn_calls

def main():
    """
    主函数，处理命令行参数
    """
    parser = argparse.ArgumentParser(description='NPM包预处理器')
    parser.add_argument('--package_dir', required=True, help='npm包的根目录路径')
    
    args = parser.parse_args()
    
    if not os.path.exists(args.package_dir):
        print(f"错误：目录不存在 {args.package_dir}")
        return
    
    js_files = process_package(args.package_dir)
    
    # 输出结果（只输出到stdout，调试信息到stderr）
    for js_file in js_files:
        print(js_file)

if __name__ == "__main__":
    main()